<?php
class CentImsRbacImpl implements IRbac {
	private $rbacModel;
	public function __construct() {
		$this->rbacModel = new CoreRbacModel ();
	}
	/*
	 * (non-PHPdoc) @see IRbac::getExtra()
	 */
	public function getExtra($op, $resource, $id, $type) {
		$where ['role'] = $type;
		$where ['role_id'] = $id;
		$where ['action'] = $op;
		$where ['resource'] = $resource;
		$extra = $this->rbacModel->get ( 'extra', $where );
		if (! empty ( $extra )) {
			return @unserialize ( $extra );
		} else {
			return array ();
		}
	}
	
	/*
	 * (non-PHPdoc) @see IRbac::grant()
	 */
	public function grant($ops, $resource, $id, $type, $priority = -1, $extra = array()) {
		if (empty ( $ops )) {
			return true;
		}
		$where ['role'] = $type;
		$where ['role_id'] = $id;
		$where ['resource'] = $resource;
		$priority = intval ( $priority );
		foreach ( $ops as $op => $allow ) {
			$where ['action'] = $op;
			if ($priority >= 0) {
				$data = array_merge ( $where, array ('allow' => intval ( $allow ), 'priority' => $priority ) );
			} else {
				$data = array_merge ( $where, array ('allow' => intval ( $allow ) ) );
			}
			$this->rbacModel->save ( $data, $where );
		}
		return true;
	}
	
	/*
	 * (non-PHPdoc) @see IRbac::icando()
	 */
	public function icando($op, $resource, $id, $type, $reload = false) {
		static $privileges = array ();
		$pkey = $id . '@' . $type;
		if ($reload || ! isset ( $privileges [$pkey] )) {
			unset ( $privileges [$pkey] );
			$types = apply_filter ( 'get_roles_for_' . $type, array (), $id );
			$type_privileges = array ();
			if (! empty ( $types )) {
				foreach ( $types as $itype => $iid ) {
					$inherit_privileges = $this->privileges ( $iid, $itype );
					if (! empty ( $inherit_privileges )) {
						foreach ( $inherit_privileges as $key => $pri ) {
							if (! isset ( $type_privileges [$key] ) || $type_privileges [$key] ['priority'] > $pri ['priority']) {
								$type_privileges [$key] = $pri;
							}
						}
					}
				}
			}
			$myprivileges = $this->privileges ( $id, $type );
			if (! empty ( $myprivileges )) {
				$privileges [$pkey] = array_merge ( $type_privileges, $myprivileges );
			} else {
				$privileges [$pkey] = $type_privileges;
			}
		}
		$privis = $privileges [$pkey];
		$key = $resource . '@' . $op;
		if (isset ( $privis [$key] )) {
			$privi = $privis [$key];
			$allow = intval ( $privi ['allow'] );
			if ($allow > 0) {
				$extra = @unserialize ( $privi ['extra'] );
				if (! empty ( $extra )) {
					return $extra;
				} else {
					return true;
				}
			} else {
				return false;
			}
		}
		$key = $resource . '@*';
		if (isset ( $privis [$key] )) {
			$privi = $privis [$key];
			$allow = intval ( $privi ['allow'] );
			if ($allow > 0) {
				$extra = @unserialize ( $privi ['extra'] );
				if (! empty ( $extra )) {
					return $extra;
				} else {
					return true;
				}
			} else {
				return false;
			}
		}
		$key = '*@*';
		if (isset ( $privis [$key] )) {
			$privi = $privis [$key];
			$allow = intval ( $privi ['allow'] );
			if ($allow > 0) {
				$extra = @unserialize ( $privi ['extra'] );
				if (! empty ( $extra )) {
					return $extra;
				} else {
					return true;
				}
			} else {
				return false;
			}
		}
		return false;
	}
	
	/*
	 * (non-PHPdoc) @see IRbac::privileges()
	 */
	public function privileges($id, $types) {
		if (empty ( $id )) {
			return array ();
		}
		$rtn = array ();
		$where ['role'] = $types;
		$where ['role_id IN'] = $id;
		$privileges = $this->rbacModel->where ( $where )->retrieve ( 'resource,action,allow,priority,extra' );
		if ($privileges) {
			foreach ( $privileges as $p ) {
				$id = $p ['resource'] . '@' . $p ['action'];
				if (! isset ( $rtn [$id] ) || $rtn [$id] ['priority'] > $p ['priority']) {
					$rtn [$id] = $p;
				}
			}
		}
		return $rtn;
	}
	
	/*
	 * (non-PHPdoc) @see IRbac::revoke()
	 */
	public function revoke($ops, $resource, $id, $type) {
		if (empty ( $ops )) {
			return true;
		}
		$where ['role'] = $type;
		$where ['role_id'] = $id;
		$where ['resource'] = $resource;
		foreach ( $ops as $op ) {
			$where ['action'] = $op;
			$this->rbacModel->delete ( $where );
		}
		return true;
	}
	
	/*
	 * (non-PHPdoc) @see IRbac::revokeAll()
	 */
	public function revokeAll($id, $type) {
		return $this->rbacModel->where ( array ('role' => $type, 'role_id' => $id ) )->delete ();
	}
	/*
	 * (non-PHPdoc) @see IRbac::setExtra()
	 */
	public function setExtra($op, $resource, $id, $type, $extra) {
		$where ['role'] = $type;
		$where ['role_id'] = $id;
		$where ['action'] = $op;
		$where ['resource'] = $resource;
		$extra = is_array ( $extra ) ? $extra : array ($extra );
		$data ['extra'] = serialize ( $extra );
		return $this->rbacModel->save ( $data, $where );
	}
}